package cn.pconline.autoclub.web;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.velocity.VelocityContext;
import org.gelivable.dao.GeliDao;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import cn.pconline.autoclub.config.SystemConfig;
import cn.pconline.autoclub.entity.CloudLog;
import cn.pconline.autoclub.entity.Club;
import cn.pconline.autoclub.entity.ClubMember;
import cn.pconline.autoclub.entity.InviteJoin;
import cn.pconline.autoclub.entity.InviteMember;
import cn.pconline.autoclub.entity.MemberAll;
import cn.pconline.autoclub.entity.MemberApplication;
import cn.pconline.autoclub.entity.MemberWeek;
import cn.pconline.autoclub.entity.User;
import cn.pconline.autoclub.exception.ApiException;
import cn.pconline.autoclub.service.CloudLogService;
import cn.pconline.autoclub.service.ClubService;
import cn.pconline.autoclub.service.IntfService;
import cn.pconline.autoclub.service.InviteJoinService;
import cn.pconline.autoclub.service.InviteMemberService;
import cn.pconline.autoclub.service.MemberService;
import cn.pconline.autoclub.service.MessageService;
import cn.pconline.autoclub.service.StatService;
import cn.pconline.autoclub.service.UserForumService;
import cn.pconline.autoclub.service.UserService;
import cn.pconline.autoclub.util.AppUtils;
import cn.pconline.autoclub.util.EncodeUtils;
import cn.pconline.autoclub.util.JsonResult;
import cn.pconline.autoclub.util.Pager;
import cn.pconline.autoclub.util.Regex;
import cn.pconline.autoclub.util.TmplUtils;
import cn.pconline.autoclub.util.WebUtils;
import cn.pconline.autoclub.util.WhoisUtil;
import cn.pconline.autoclub.util.mail.MailSenderInfo;
import cn.pconline.autoclub.util.mail.SimpleMailSender;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

@Controller
public class UserController {

    @Autowired
    private UserService userService;
    @Autowired
    private MemberService memberService;
    @Autowired
    private ClubService clubService;
    @Autowired
    private MessageService messageService;
    @Autowired
    private UserAuth userAuth;
    @Autowired
    private SystemConfig systemConfig;
    @Autowired
    private IntfService intfService;
    @Autowired
    private TokenController tokenController;
    @Autowired
    private StatService statService;
    @Autowired
    private InviteJoinService inviteJoinService;
    @Autowired
    private InviteMemberService inviteMemberService;
    @Autowired
    private UserForumService userForumService;
    @Autowired
    private GeliDao geliDao;
    @Autowired
    private CloudLogService cloudLogService;
    private static final Logger log = LoggerFactory.getLogger(UserController.class);
    public static int NEW_MEMBER_COUNT = 9;
    private final static int MAX_PAGESIZE = 100;
    private final static int MIN_PAGESIZE = 1;
    private static final int PORTRAIT_WIDTH = 50;//头像宽度
    private static final double LAT_LNG_SIZE = 0.2;//相关的经纬度度数
    private final static int TYPE_ALL = 1;
    private final static int TYPE_CERTIFIED = 2;
    private final static int TYPE_ORDINARY = 3;
    private final static int DB_MAX_LENGTH = 255; //爱车最大长度
    private final static int TRUENAME_MAX_LENGTH = 10; //真实姓名最大长度
    /**
     * 拼接用户头像图片,域名：http://i6.3conline.com/images/upload/upc/face/
     */
    private static final long AUTHORPHOTO_URL_I6 = 6L;

    /**
     * 会员申请页面跳转
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/member/getApplyInfo", method = RequestMethod.GET)
    @ResponseBody
    public void getApplyInfo(HttpServletRequest request, HttpServletResponse response) {
        WebUtils.setEncoding(request, response);
        User user = userAuth.getUser(request, response);
        long clubId = WebUtils.paramLong(request, "clubId", 0);
        Club club = clubService.getValidClub(clubId);
        if (club == null) {
            printWriter(response, new JsonResult(JsonResult.STATUS_ILLEGAL_ARGUMENT, "车友会不存在！").toString2());
            return;
        }
        if (user.getUid() <= 0) {
            printWriter(response, new JsonResult(JsonResult.STATUS_AUTH_FAILED, "未登录").toString2());
            return;
        }
        // 先判断有没有提交过申请
        List<MemberApplication> apps = memberService.findMemberApplication(user.getUid(), 0l, true);
        boolean applied = false;
        for (MemberApplication app : apps) {
            if (app.getClubId() == clubId) {
                applied = true;
            }
        }
        if (applied) {
            printWriter(response, new JsonResult(JsonResult.STATUS_ERROR, "您已经申请加入了该车友会，请等候审核。").toString2());
            return;
        }
        //判断是否已经加入了改车友会
        if (memberService.countByclubIdUid(clubId, user.getUid()) != null) {
            printWriter(response, new JsonResult(JsonResult.STATUS_ERROR, "您已经加入了该车友会。").toString2());
            return;
        }

        int joinClubLimit = NumberUtils.toInt(systemConfig.getJoinClubLimit());
        int count = userService.updateJoinedClubCount(user);
        count += apps.size();
        count += clubService.findByFounder(user.getUid(), true).size();
        if (count >= joinClubLimit) {
            printWriter(response, new JsonResult(JsonResult.STATUS_ERROR, "您已经加入了其他车友会，无法申请。").toString2());
            return;
        }
        if (!user.isComplete() || StringUtils.isBlank(user.getCarInfo())) {
            JsonResult rs = new JsonResult(JsonResult.STATUS_SUCCESS, "");
            rs.setResult(user.toJson().toJSONString());
            printWriter(response, rs.toString2());
            return;
        }
        String result = applyMembership(user, clubId, request, response);
        if (StringUtils.isEmpty(result)) {
            JsonResult rs = new JsonResult(JsonResult.STATUS_SUCCESS, "申请完成！");
            printWriter(response, rs.toString2());
        } else {
            printWriter(response, new JsonResult(JsonResult.STATUS_ERROR, result).toString2());
        }
    }

    /**
     * 提交入会申请
     *
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    @RequestMapping(value = "/member/apply", method = RequestMethod.POST)
    @ResponseBody
    public void applyMembership(HttpServletRequest request, HttpServletResponse response) throws IOException {
        WebUtils.setEncoding(request, response);
        User user = userAuth.getUser(request, response);
        long clubId = WebUtils.paramLong(request, "clubId", 0);
        Club club = clubService.getValidClub(clubId);
        if (club == null) {
            printWriter(response, new JsonResult(JsonResult.STATUS_ILLEGAL_ARGUMENT, "车友会不存在！").toString2());
            return;
        }
        if (user.getUid() <= 0) {
            printWriter(response, new JsonResult(JsonResult.STATUS_AUTH_FAILED, "未登录").toString2());
            return;
        }
        String result = applyMembership(user, clubId, request, response);
        if (StringUtils.isEmpty(result)) {
            JSONObject obj = new JSONObject();
            obj.put("status", JsonResult.STATUS_SUCCESS);
            obj.put("clubId", clubId);
            obj.put("desc", "恭喜，您的申请已经提交，请等待会长的审核！");
            response.getWriter().println(obj.toString());
            return;
        }
        response.getWriter().println(result);
        response.getWriter().close();
    }

    /**
     * 提交入会申请(通过普通会员给的邀请链接)
     *
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    @RequestMapping(value = "/member/inviteApply", method = RequestMethod.POST)
    @ResponseBody
    public void applyMembershipByInvite(HttpServletRequest request, HttpServletResponse response) throws IOException {
        WebUtils.setEncoding(request, response);
        long clubId = WebUtils.paramLong(request, "clubId", 0);
        if (clubId <= 0) {
            response.getWriter().println(new JsonResult(JsonResult.STATUS_ILLEGAL_ARGUMENT, "车友会不存在").toString());
            return;
        }
        String result = inviteApplyMembership(clubId, request, response);
        if (StringUtils.isEmpty(result)) {
            Club club = clubService.getValidClub(clubId);

            Cookie c = new Cookie("isApplySuccess", "true");
            c.setPath("/");
            c.setDomain(".pcauto.com.cn");
            //     c.setMaxAge(10);
            response.addCookie(c);
            JSONObject obj = new JSONObject();
            obj.put("status", JsonResult.STATUS_SUCCESS);
            obj.put("url", club.getClubUrl());
            obj.put("clubId", clubId);
            obj.put("desc", "恭喜，您的申请已经提交，请等待会长的审核！");

            response.getWriter().println(obj.toString());
            return;
        }
        response.getWriter().println(result);
        response.getWriter().close();
    }

    /**
     * 入会审核 权限验证：管理员即可(APP共用)
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/member/audit", method = RequestMethod.POST)
    @ResponseBody
    public void auditMemberApplication(HttpServletRequest request, HttpServletResponse response) {
        WebUtils.setEncoding(request, response);
        long applicationId = WebUtils.paramLong(request, "applicationId", 0);
        String callback = WebUtils.param(request, "callback", "");
        String retStr;
        MemberApplication application = memberService.findMemberApplication(applicationId);
        int action = WebUtils.paramInt(request, "action", 0);
        User user = userAuth.getUser(request, response);
        long clubId = WebUtils.paramLong(request, "clubId", 0);
        ClubMember member = memberService.findMember(user.getUid(), clubId);
        if (application == null) {
            retStr = new JsonResult(JsonResult.STATUS_ERROR, "审核失败，该申请已被处理").toString();
            printWriter(response, retStr, callback);
            return;
        }
        if (clubService.getValidClub(application.getClubId()) == null) {
            retStr = new JsonResult(JsonResult.STATUS_ERROR, "车友会不存在").toString();
            printWriter(response, retStr, callback);
            return;
        }
        if (member == null || !member.isAdministrator()) {
            retStr = new JsonResult(JsonResult.STATUS_AUTH_FAILED, "您不是该车友会管理员，只有管理员才能进行该操作哦！").toString();
            printWriter(response, retStr, callback);
            return;
        }
        if (application.getStatus() == MemberApplication.STATUS_PASS) {
            retStr = new JsonResult(JsonResult.STATUS_ERROR, "审核失败，该申请已被通过").toString();
            printWriter(response, retStr, callback);
            return;
        }
        if (application.getStatus() == MemberApplication.STATUS_REJECT) {
            retStr = new JsonResult(JsonResult.STATUS_ERROR, "审核失败，该申请已被拒绝").toString();
            printWriter(response, retStr, callback);
            return;
        }
        if (application.getStatus() == MemberApplication.STATUS_CANCEL) {
            retStr = new JsonResult(JsonResult.STATUS_ERROR, "审核失败，用户已取消申请").toString();
            printWriter(response, retStr, callback);
            return;
        }
        boolean isSuccess = false;
        if (action == MemberApplication.STATUS_PASS) {
            isSuccess = memberService.passMemberApplication(application, user.getUid());
            if (isSuccess) {
                //通过车友会申请后，调用融云加入聊天群接口
                String userId_s = "";
                String clubId_s = "";
                String clubName = "";
                try {
                    userId_s = String.valueOf(member.getUid());
                    clubId_s = String.valueOf(member.getClubId());
                    Club club = clubService.getClub(member.getClubId());
                    if (club != null) {
                        clubName = club.getName();
                    }
                    boolean joinFlag = tokenController.joinClub(userId_s, clubId_s, clubName);
                    if (!joinFlag) {
                    	//插入融云失败的日志记录
                    	cloudLogService.create(clubId,clubName,user.getUid(),CloudLog.JOIN_CLOUD);
                        log.error("调用融云加入群API失败!userId=" + userId_s + ",clubId=" + clubId_s + ",clubName=" + clubName);
                    }
                } catch (ApiException exception) {
                	//插入融云失败的日志记录
                	cloudLogService.create(clubId,clubName,user.getUid(),CloudLog.JOIN_CLOUD);
                    log.error("调用融云加入群API异常！userId=" + userId_s + ",clubId=" + clubId_s + ",clubName=" + clubName, exception);
                }

                //审核通过发短信和邮件通知
                User applicationUser = userService.findUser(application.getUid());
                Club club = clubService.getClub(clubId);
                if (club != null && applicationUser != null) {
                    //发短信通知会员
                    messageService.sendSMS(applicationUser.getPhone(), applicationUser.getUid(), MessageService.APPLY_PASS_SMS, club.getName());
                    //发邮件通知会员
                    if (applicationUser.getEmail() != null && applicationUser.getEmail().matches(Regex.email.value)) {
                        String[] mailToAddress = {applicationUser.getEmail()};
                        String subject = String.format(MessageService.APPLY_PASS_MAIL_SUBJECT, club.getName());
                        VelocityContext velocityContext = new VelocityContext();
                        velocityContext.put("nickName", applicationUser.getNickname());
                        velocityContext.put("clubName", club.getName());
                        velocityContext.put("clubUrl", club.getClubUrl());
                        velocityContext.put("ucRoot", systemConfig.getUcRoot());
                        velocityContext.put("userId", applicationUser.getUid());
                        velocityContext.put("root", systemConfig.getRoot());
                        String content = TmplUtils.render(systemConfig.getDataPath() + File.separator, "applyPassMailTempate.html", velocityContext);
                        MailSenderInfo mailInfo = SimpleMailSender.getSenderInfo(systemConfig.getMailServerHost(), systemConfig.getMailServerPort(),
                                true, systemConfig.getMailPassWord(), systemConfig.getFromAddress(), mailToAddress, subject, content);
                        if (SimpleMailSender.sendHtmlMail(mailInfo)) {
                            log.info("success to send mail for user[{}]", applicationUser.getUid());
                        } else {
                            log.error("fail success to send mail for user[{}]", applicationUser.getUid());
                        }
                    }
                }
                //加入车友会之后，初始化车友圈
                userForumService.createIfNothing(applicationUser.getUid(), applicationUser.getCityId(), applicationUser.getProvinceId(), applicationUser.getCarInfo());
            }
        } else if (action == MemberApplication.STATUS_REJECT) {
            isSuccess = memberService.rejectMemberApplication(application, user.getUid());
        }
        if (isSuccess) {
            retStr = new JsonResult(JsonResult.STATUS_SUCCESS, "ok").toString();
        } else {
            retStr = new JsonResult(JsonResult.STATUS_ERROR, "审核失败").toString();
        }
        printWriter(response, retStr, callback);
    }

    /**
     * 会员列表
     *
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    @RequestMapping(value = "/member/manage", method = RequestMethod.GET)
    public String toMemberManagement(HttpServletRequest request, HttpServletResponse response) throws IOException {
        long clubId = WebUtils.paramLong(request, "clubId", 0);
        Club club = clubService.getValidClub(clubId);
        int pageNo = WebUtils.paramInt(request, "pageNo", 1);
        int pageSize = WebUtils.paramInt(request, "pageSize", 15, MIN_PAGESIZE, MAX_PAGESIZE);
        if (club == null || pageNo < 1) {
            try {
                response.sendError(404);
            } catch (Exception e) {
                log.error("toMemberManagement response.sendError(404) 失败", e);
            }
            return "/template/common/notFoundPage";
        }
        request.setAttribute("club", club);
        request.setAttribute("clubId", clubId);
        List<MemberApplication> applications = memberService.listMemberApplications4Audit(clubId);
        request.setAttribute("applications", applications);
        Pager<ClubMember> members = memberService.getClubMemberPage(clubId, 0l, pageNo, pageSize);
        WebUtils.checkPageMaxNo(response, pageNo, members.getPageCount());
        request.setAttribute("members", members);

        List<ClubMember> admins = memberService.listAdmins(clubId);
        request.setAttribute("admins", admins);

        List<ClubMember> newMembers = memberService.listNewMembers(clubId, NEW_MEMBER_COUNT);
        request.setAttribute("newMembers", newMembers);

        User loginUser = userAuth.getUser(request, response);
        if (loginUser.getUid() != 0L) {
            request.setAttribute("user", loginUser);
            ClubMember clubMember = memberService.findMember(loginUser.getUid(), clubId);
            request.setAttribute("loginClubMember", clubMember);
        }
        return "template/member/member";
    }

    /**
     * 权限转移
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/member/assignAdmin", method = RequestMethod.POST)
    @ResponseBody
    public String assignAdmin(HttpServletRequest request, HttpServletResponse response) {
        User user = userAuth.getUser(request, response);
        long clubId = WebUtils.paramLong(request, "clubId", 0);
        if (clubService.getValidClub(clubId) == null) {
            return new JsonResult(JsonResult.STATUS_AUTH_FAILED, "车友会不存在").toString();
        }
        ClubMember operator = memberService.findMember(user.getUid(), clubId);
        if (operator == null || !operator.isAdmin()) {
            return new JsonResult(JsonResult.STATUS_AUTH_FAILED, "没有权限").toString();
        }
        int type = WebUtils.paramInt(request, "type", 0);
        long memberId = WebUtils.paramLong(request, "memberId", 0);
        ClubMember member = memberService.find(memberId);
        if (member == null) {
            return new JsonResult(JsonResult.STATUS_ILLEGAL_STATE, "用户不存在").toString();
        }
        memberService.adminAssignment(operator, member, type);
        return new JsonResult(JsonResult.STATUS_SUCCESS, "ok").toString();
    }

    /**
     * 移除车友会
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/member/kick", method = RequestMethod.POST, produces = {"text/html;charset=UTF-8"})
    @ResponseBody
    public String kick(HttpServletRequest request, HttpServletResponse response) {
        String originHeader = request.getHeader("Origin");
        if (originHeader != null) {
            response.setHeader("Access-Control-Allow-Credentials", "true");
            response.setHeader("Access-Control-Allow-Origin", originHeader);
        }
        response.setCharacterEncoding("UTF-8");
        User user = userAuth.getUser(request, response);
        long clubId = WebUtils.paramLong(request, "clubId", 0);
        long memberId = WebUtils.paramLong(request, "memberId", 0);
        int windowName = WebUtils.paramInt(request, "windowname", 0);
        Club club = clubService.getValidClub(clubId);
        if (user == null || user.getUid() < 1) {
            return parseWindowNameString(new JsonResult(JsonResult.STATUS_AUTH_FAILED, "用户未登录").toString(), windowName);
        }
        if (club == null) {
            return parseWindowNameString(new JsonResult(JsonResult.STATUS_AUTH_FAILED, "车友会不存在").toString(), windowName);
        }
        ClubMember operator = memberService.findMember(user.getUid(), clubId); //操作人
        ClubMember member = memberService.find(memberId);//操作对象
        if (member == null) {
            return parseWindowNameString(new JsonResult(JsonResult.STATUS_AUTH_FAILED, "找不到该会员").toString(), windowName);
        }
        //判断是不是退出车友会
        int result;
        String clubIndexUrl = messageService.assembleClubUrl(club.getClubUrl(), club.getName());
        String passMsg; //系统消息
        if (member.getUid() == user.getUid()) {
            //退出车友会
            if (member.getAdminType() == ClubMember.ADMIN) {
                return parseWindowNameString(new JsonResult(JsonResult.STATUS_ERROR, "请转让会长后再退出车友会").toString(), windowName);
            } else {
                result = memberService.expelMember(member, member);
            }
            //组装系统消息主体
            passMsg = String.format(MessageService.EXIT_CLUB, clubIndexUrl, user.getNickname());
        } else {
            //权限移除其他人员退出车友会
            if (operator == null || !operator.isAdministrator()) {
                return parseWindowNameString(new JsonResult(JsonResult.STATUS_AUTH_FAILED, "没有权限").toString(), windowName);
            }
            //组装系统消息主体
            passMsg = String.format(MessageService.FIRED_CLUB, clubIndexUrl);
            result = memberService.expelMember(operator, member);
        }

        if (result > 0) {
            //发送系统消息
            if (member.getUid() == user.getUid()) { //退出车友会时通知管理员
                List<ClubMember> users = memberService.listAdmins(clubId);
                for (ClubMember m : users) {
                    User u = userService.findUser(m.getUid());
                    if (u != null) {
                        messageService.send(u, passMsg);
                    }
                }
            } else { //移除车友会时通知被操作人
                messageService.send(userService.findUser(member.getUid()), passMsg);
            }

            //调用融云退出群接口
            String userId_s = "";
            String clubId_s = "";
            try {
                userId_s = String.valueOf(member.getUid());
                clubId_s = String.valueOf(member.getClubId());
                boolean quitFlag = tokenController.QuitClub(userId_s, clubId_s);
                if (!quitFlag) {
                	//插入失败日志
                	cloudLogService.create(club.getClubId(),club.getName(),user.getUid(),CloudLog.QUIT_CLOUD);
                    log.error("调用融云退出群API失败!userId=" + userId_s + ",clubId=" + clubId_s);
                }
            } catch (ApiException exception) {
            	//插入失败日志
            	cloudLogService.create(club.getClubId(),club.getName(),user.getUid(),CloudLog.QUIT_CLOUD);
                log.error("调用融云退出群API异常！userId=" + userId_s + ",clubId=" + clubId_s);
            }
            return parseWindowNameString(new JsonResult(JsonResult.STATUS_SUCCESS, "ok").toString(), windowName);
        } else {
            return parseWindowNameString(new JsonResult(JsonResult.STATUS_ERROR, "failed").toString(), windowName);
        }
    }

    /**
     * 转换为windowName格式
     *
     * @param str 数据正文
     * @param windowName 0 不转，1 转换windowname格式
     * @return
     */
    private String parseWindowNameString(String str, int windowName) {
        if (windowName > 0) {
            return "<script>window.name='" + str + "'</script>";
        }
        return str;
    }

    /**
     * 同步个人中心昵称
     *
     * @param request
     * @param resp
     */
    @RequestMapping("/user/updateNickName")
    public void updateNickName(HttpServletRequest request, HttpServletResponse resp) {

        String ip = WhoisUtil.getIp(request);
        boolean inList = ip.startsWith("192.168");
//        List<String> machineList = appConfigService.getValueListByName("ScoreClientMachine");
//        boolean inList = false;
//        for (String mac : machineList) {
//            if (ip.contains(mac)) {
//                inList = true;
//                break;
//            }
//        }

        PrintWriter out = null;
        try {
            request.setCharacterEncoding("GBK");
            String msg = request.getParameter("msg");
            out = resp.getWriter();
            JSONObject result = new JSONObject();
            if (!inList || StringUtils.isEmpty(msg)) {
                result.put("code", -1); //更新失败 msg为空
                out.print(result);
                return;
            }
            JSONObject jo = JSONObject.parseObject(msg);
            JSONObject json = (JSONObject) jo.get("msg");

            long accountId = Long.parseLong(String.valueOf(json.get("accountId")));
            String nickName = (String) json.get("nickName");
            User user = this.userService.findUser(accountId);
            if (user != null) {
                user.setNickname(nickName);
                userService.updateUser(user);
                result.put("code", 0); // 更新成功
                out.print(result);
            }

        } catch (IOException ex) {
            log.error("同步个人中心昵称接口异常！", ex);
        } finally {
            out.close();
        }
    }

    /**
     * 返回空串表示操作成功
     *
     * @param clubId
     * @param request
     * @param response
     * @return
     */
    private String applyMembership(User user, long clubId, HttpServletRequest request, HttpServletResponse response) {
        String phone = WebUtils.paramTrim(request, "phone", "");
        String trueName = WebUtils.paramTrim(request, "truename", user.getTruename());
        int gender = WebUtils.paramInt(request, "gender", 0);
        String provinceName = WebUtils.paramTrim(request, "provinceName", "");
        long provinceId = WebUtils.paramLong(request, "provinceId", 0);
        String cityName = WebUtils.getAreaPlaceByReq(request, "cityName", "");
        long cityId = WebUtils.paramLong(request, "cityId", 0);

        if (!user.isComplete() || StringUtils.isBlank(user.getCarInfo())) {
            if (StringUtils.isNotEmpty(phone) && !phone.matches(Regex.cellphone.value)) {
                return new JsonResult(JsonResult.STATUS_ILLEGAL_STATE, "请输入正确的手机号码").toString();
            }
            //手机没验证才储存绑定手机
            if (user.getPhoneValidated() == User.NOT_PHONE_VALIDATED) {
            	user.setPhone(phone);
            }

            if (StringUtils.isNotEmpty(trueName) && (trueName.length() > TRUENAME_MAX_LENGTH 
            		|| !trueName.matches(Regex.trueName.value))) {
                return new JsonResult(JsonResult.STATUS_ILLEGAL_STATE, "请输入合法的中文姓名").toString();
            }
            user.setTruename(trueName);


            user.setGender(gender);

            if (StringUtils.isNotEmpty(provinceName) && provinceName.length() > DB_MAX_LENGTH) {
                return new JsonResult(JsonResult.STATUS_ILLEGAL_STATE, "非法的省份名称").toString();
            }
            user.setProvinceId(provinceId);
            user.setProvince(provinceName);

            if (StringUtils.isNotEmpty(cityName) && cityName.length() > DB_MAX_LENGTH) {
                return new JsonResult(JsonResult.STATUS_ILLEGAL_STATE, "非法的城市名称").toString();
            }
            user.setCityId(cityId);
            user.setCity(cityName);
            //获取请求中的爱车信息
            String carInfo = getCarInfo(request);
            //返回null代表爱车信息有误
            if (carInfo == null) {
                return new JsonResult(JsonResult.STATUS_ILLEGAL_STATE, "非法的爱车信息").toString();
            }
            user.setCarInfo(carInfo);
            userService.updateUser(user);
        }
        if (!memberService.findMemberApplication(user.getUid(), clubId, true).isEmpty()) {
            return new JsonResult(JsonResult.STATUS_ILLEGAL_STATE, "您已经申请加入了该车友会，请等候审核。").toString();
        }
        if (!memberService.listClubMemberByUser(user.getUid()).isEmpty() || !clubService.findByFounder(user.getUid(), true).isEmpty()) { //已经申请加入另一个车友会 或 已创建一个车友会待审核
            return new JsonResult(JsonResult.STATUS_ILLEGAL_STATE, "您只能申请或加入一个车友会").toString();
        }
        if (memberService.countByclubIdUid(clubId, user.getUid()) != null) {
            return new JsonResult(JsonResult.STATUS_ILLEGAL_STATE, "您已经加入了该车友会。").toString();
        }
        int joinClubLimit = NumberUtils.toInt(systemConfig.getJoinClubLimit());
        int count = userService.updateJoinedClubCount(user);
        if (count >= joinClubLimit) {
            return new JsonResult(JsonResult.STATUS_ILLEGAL_STATE, "您已经加入了其他车友会，无法申请。").toString();
        }
        Club club = clubService.getValidClub(clubId);
        if (club == null) {
            return new JsonResult(JsonResult.STATUS_ILLEGAL_STATE, "车友会已经被锁定").toString();
        }
        memberService.applyMembership(user, club);//创建入会申请

        String clubUrl = clubService.getClubIndexUrl(club.getClubId(), club.getClubUrl());
        String msg1 = messageService.assembleClubUrl(club.getClubUrl(), club.getName());
        String msg2 = String.format("<a href=\"%s\" target=\"_blank\">%s</a>", clubUrl + "member/", "会员列表");

        //通知车友会管理员去审核
        List<ClubMember> admins = memberService.listAdmins(clubId);
        for (ClubMember m : admins) {
            messageService.send(userService.findUser(m.getUid()), MessageService.APPLY_RECEIVED, msg1, user.getNickname(), msg2);
        }
        //同步个人中心省市，车系车型
        int serialId = WebUtils.paramInt(request, "serialId", 0);
        if (serialId > 0) {
            intfService.checkBrandSerial(WebUtils.paramInt(request, "brandId", 0),
                    serialId,
                    systemConfig.getUserSessionName(),
                    WebUtils.cookie(request, systemConfig.getUserSessionName()));
        }

        //当没选择市传省ID,都没选择不传
        long domicileId = cityId > 0 ? cityId : provinceId > 0 ? provinceId : 0;
        //同步个人资料到个人中心
        String commonSessionId = cn.pconline.passport2.util.WebUtils.getCookie(request, systemConfig.getUserSessionName());
        intfService.updateUserCenter(commonSessionId, trueName, null, gender, phone, null, null, domicileId, null);
        return "";
    }

    /**
     * 返回空串表示操作成功(一键邀请)
     *
     * @param clubId
     * @param request
     * @param response
     * @return
     */
    private String inviteApplyMembership(long clubId, HttpServletRequest request, HttpServletResponse response) {
        User user = userAuth.getUser(request, response);
        if (user.getUid() <= 0) {
            return new JsonResult(JsonResult.STATUS_AUTH_FAILED, "没有登录").toString();
        }

        String phone = WebUtils.paramTrim(request, "telePhone", "");
        String nickName = WebUtils.paramTrim(request, "nickName", user.getNickname());
        int gender = WebUtils.paramInt(request, "gender", 0);
        String provinceName = WebUtils.paramTrim(request, "provinceName", "");
        long provinceId = WebUtils.paramLong(request, "provinceId", 0);
        String cityName = WebUtils.getAreaPlaceByReq(request, "cityName", "");
        long cityId = WebUtils.paramLong(request, "cityId", 0);

        if (!user.isComplete() || StringUtils.isBlank(user.getCarInfo())) {
            if (StringUtils.isNotEmpty(phone) && !phone.matches(Regex.cellphone.value)) {
                return new JsonResult(JsonResult.STATUS_ILLEGAL_STATE, "请输入正确的手机号码").toString();
            }
            user.setPhone(phone);

            if (StringUtils.isBlank(nickName) || !nickName.matches("([a-zA-Z0-9_]|[^\\x00-\\xff])+")) {
                return new JsonResult(JsonResult.STATUS_ILLEGAL_STATE, "请输入合法的昵称").toString();
            }
            user.setNickname(nickName);

            user.setGender(gender);

            if (StringUtils.isNotEmpty(provinceName) && provinceName.length() > DB_MAX_LENGTH) {
                return new JsonResult(JsonResult.STATUS_ILLEGAL_STATE, "非法的省份名称").toString();
            }
            user.setProvinceId(provinceId);
            user.setProvince(provinceName);

            if (StringUtils.isNotEmpty(cityName) && cityName.length() > DB_MAX_LENGTH) {
                return new JsonResult(JsonResult.STATUS_ILLEGAL_STATE, "非法的城市名称").toString();
            }
            user.setCityId(cityId);
            user.setCity(cityName);
            //获取请求中的爱车信息
            String carInfo = getCarInfo(request);
            //返回null代表爱车信息有误
            if (carInfo == null) {
                return new JsonResult(JsonResult.STATUS_ILLEGAL_STATE, "非法的爱车信息").toString();
            }
            user.setCarInfo(carInfo);
            userService.updateUser(user);

        }
        if (!memberService.findMemberApplication(user.getUid(), clubId, true).isEmpty()) {
            return new JsonResult(JsonResult.STATUS_ILLEGAL_STATE, "您已经申请加入了该车友会，请等候审核。").toString();
        }
        if (!memberService.listClubMemberByUser(user.getUid()).isEmpty() || !clubService.findByFounder(user.getUid(), true).isEmpty()) { //已经申请加入另一个车友会 或 已创建一个车友会待审核
            return new JsonResult(JsonResult.STATUS_ILLEGAL_STATE, "您只能申请或加入一个车友会").toString();
        }
        if (memberService.countByclubIdUid(clubId, user.getUid()) != null) {
            return new JsonResult(JsonResult.STATUS_ILLEGAL_STATE, "您已经加入了该车友会。").toString();
        }
        int joinClubLimit = NumberUtils.toInt(systemConfig.getJoinClubLimit());
        int count = userService.updateJoinedClubCount(user);
        if (count >= joinClubLimit) {
            return new JsonResult(JsonResult.STATUS_ILLEGAL_STATE, "您已经加入了其他车友会，无法申请。").toString();
        }
        Club club = clubService.getValidClub(clubId);
        if (club == null) {
            return new JsonResult(JsonResult.STATUS_ILLEGAL_STATE, "车友会已经被锁定").toString();
        }
        memberService.applyMembership(user, club);//创建入会申请

        String clubUrl = clubService.getClubIndexUrl(club.getClubId(), club.getClubUrl());
        String msg1 = messageService.assembleClubUrl(club.getClubUrl(), club.getName());
        String msg2 = String.format("<a href=\"%s\" target=\"_blank\">%s</a>", clubUrl + "member/", "会员列表");

        //通知车友会管理员去审核
        List<ClubMember> admins = memberService.listAdmins(clubId);
        for (ClubMember m : admins) {
            messageService.send(userService.findUser(m.getUid()), MessageService.APPLY_RECEIVED, msg1, user.getNickname(), msg2);
        }
        //同步个人中心省市，车系车型
        int serialId = WebUtils.paramInt(request, "serialId", 0);
        if (serialId > 0) {
            intfService.checkBrandSerial(WebUtils.paramInt(request, "brandId", 0),
                    serialId,
                    systemConfig.getUserSessionName(),
                    WebUtils.cookie(request, systemConfig.getUserSessionName()));
        }

        //当没选择市传省ID,都没选择不传
        long domicileId = cityId > 0 ? cityId : provinceId > 0 ? provinceId : 0;
        //同步个人资料到个人中心
        String commonSessionId = cn.pconline.passport2.util.WebUtils.getCookie(request, systemConfig.getUserSessionName());
        intfService.updateUserCenter(commonSessionId, null, nickName, gender, phone, null, null, domicileId, null);
        return "";
    }

    /**
     * 会员列表接口
     *
     * @throws
     */
    @ResponseBody
    @RequestMapping(value = "/member/getMemberByClubId.do", method = RequestMethod.GET)
    public JSONObject getMemberByClubId(HttpServletRequest req, HttpServletResponse resp) {
        WebUtils.setEncoding(req, resp);
        long clubId = WebUtils.paramLong(req, "clubId", 0);
        int isShowAdmin = WebUtils.paramInt(req, "isShowAdmin", 0);//1》》显示  0》》隐藏 
//        long userId = WebUtils.paramLong(req, "userId", 0);
        User user = userAuth.getUser(req, resp);
        int pageNo = WebUtils.paramInt(req, "pageNo", 1);
        int pageSize = WebUtils.paramInt(req, "pageSize", 20, MIN_PAGESIZE, MAX_PAGESIZE);
        int sourceAgent = WebUtils.paramInt(req, "source_agent", 2);
        JSONObject json = new JSONObject();
        json.put("clubId", clubId);
        json.put("adminType", clubService.getClubRelationByUser(user, clubId));
        if (clubService.getValidClub(clubId) != null) {
            if (isShowAdmin > 0) {
                List<ClubMember> listAdmin = memberService.listAdmins(clubId);
                if (listAdmin != null && !listAdmin.isEmpty()) {
                    json.put("admins", member2Json(listAdmin, sourceAgent));
                }
                Pager<ClubMember> pager = memberService.pagerMemberByType(clubId, ClubMember.NON_ADMIN, pageNo, pageSize);
                if (pager.getResultList() != null && !pager.getResultList().isEmpty()) {
                    json.put("members", member2Json(pager.getResultList(), sourceAgent));
                    json.put("total", pager.getTotal());
                    json.put("pageNo", pager.getPageNo());
                    json.put("pageSize", pager.getPageSize());
                }
            } else {
                Pager<ClubMember> pager = memberService.getClubMemberPage(clubId, 0l, pageNo, pageSize);
                if (pager.getResultList() != null && !pager.getResultList().isEmpty()) {
                    json.put("total", pager.getTotal());
                    json.put("pageNo", pager.getPageNo());
                    json.put("pageSize", pager.getPageSize());
                    json.put("data", member2Json(pager.getResultList(), sourceAgent));
                }
            }
            if (user != null && user.getUid() > 0 && memberService.isClubNormalAdmin(user.getUid(), clubId)) {
                List<MemberApplication> listApply = memberService.listMemberApplications4Audit(clubId);
                JSONArray jsonArray = new JSONArray();
                if (listApply != null && !listApply.isEmpty()) {
                    for (MemberApplication apply : listApply) {
                        JSONObject obj = new JSONObject();
                        obj.put("userId", apply.getUid());
                        obj.put("memberId", apply.getId());
                        obj.put("photo", WebUtils.face(apply.getUid(), PORTRAIT_WIDTH));
                        obj.put("name", EncodeUtils.encodeForHTML(apply.getUser().getUsername(), sourceAgent));
                        obj.put("nickname", EncodeUtils.encodeForHTML(apply.getUser().getNickname(), sourceAgent));
                        obj.put("truename", EncodeUtils.encodeForHTML(apply.getUser().getTruename(), sourceAgent));
                        String info;
                        if (apply.getUser().getVip() == 0) {
                            info = WebUtils.car(apply.getUser().getCarInfo());
                        } else {
                            info = WebUtils.car(apply.getUser().getVipInfo());
                        }
                        obj.put("vipInfo", info);
                        obj.put("province", EncodeUtils.encodeForHTML(apply.getUser().getProvince(), sourceAgent));
                        obj.put("city", EncodeUtils.encodeForHTML(apply.getUser().getCity(), sourceAgent));
                        obj.put("phone", EncodeUtils.encodeForHTML(apply.getUser().getPhone(), sourceAgent));
                        jsonArray.add(obj);
                    }
                    json.put("applys", jsonArray);
                }
            }
            AppUtils.setSuccessCode(json);
            json.put("adminType", clubService.getClubRelationByUser(user, clubId));

        } else {
            AppUtils.setDataErrorCode(json, "车友会不存在");
        }
        return json;
    }

    /**
     * 会员列表接口(有缓存)
     *
     * @throws
     */
    @RequestMapping(value = "/member/getMemberByClubIdForCache.do", method = RequestMethod.GET)
    public void getMemberByClubIdForCache(HttpServletRequest req, HttpServletResponse resp) {
        WebUtils.setCacheHeader(resp, 3600);//缓存 1h
        WebUtils.setEncoding(req, resp);
        long clubId = WebUtils.paramLong(req, "clubId", 0);
        int isShowAdmin = WebUtils.paramInt(req, "isShowAdmin", 0);//1》》显示  0》》隐藏 
//        long userId = WebUtils.paramLong(req, "userId", 0);
        //User user = userAuth.getUser(req, resp);
        int pageNo = WebUtils.paramInt(req, "pageNo", 1);
        int pageSize = WebUtils.paramInt(req, "pageSize", 20, MIN_PAGESIZE, MAX_PAGESIZE);
        int sourceAgent = WebUtils.paramInt(req, "source_agent", 2);
        String callback = WebUtils.param(req, "callback", "");
        callback = EncodeUtils.encodeForHTMLFilterNull(callback);
        JSONObject json = new JSONObject();
        json.put("clubId", clubId);
        if (clubService.getValidClub(clubId) != null) {
            if (isShowAdmin > 0) {
                List<ClubMember> listAdmin = memberService.listAdmins(clubId);
                if (listAdmin != null && !listAdmin.isEmpty()) {
                    json.put("admins", member2Json(listAdmin, sourceAgent));
                }
                Pager<ClubMember> pager = memberService.pagerMemberByType(clubId, ClubMember.NON_ADMIN, pageNo, pageSize);
                if (pager.getResultList() != null && !pager.getResultList().isEmpty()) {
                    json.put("members", member2Json(pager.getResultList(), sourceAgent));
                    json.put("total", pager.getTotal());
                    json.put("pageNo", pager.getPageNo());
                    json.put("pageSize", pager.getPageSize());
                }
            } else {
                Pager<ClubMember> pager = memberService.getClubMemberPage(clubId, 0l, pageNo, pageSize);
                if (pager.getResultList() != null && !pager.getResultList().isEmpty()) {
                    json.put("total", pager.getTotal());
                    json.put("pageNo", pager.getPageNo());
                    json.put("pageSize", pager.getPageSize());
                    json.put("data", member2Json(pager.getResultList(), sourceAgent));
                }
            }
            AppUtils.setSuccessCode(json);
        } else {
            AppUtils.setDataErrorCode(json, "车友会不存在");
        }
        try {
            JsonResult jsonResult = new JsonResult();
            jsonResult.setCallback(callback);
            jsonResult.setResult(json.toJSONString());
            PrintWriter out = resp.getWriter();
            out.println(jsonResult.toString());
            out.flush();
            out.close();
        } catch (IOException ex) {
            log.error("会员列表接口异常！", ex);
        }
    }

    /**
     * 移动接口对象转json
     *
     * @param sourceAgent
     *
     * @param sourceAgent
     *
     * @param member
     * @return
     */
    public JSONArray member2Json(List<ClubMember> listAdmin, int sourceAgent) {
        JSONArray jsonArray = new JSONArray();
        for (ClubMember clubMember : listAdmin) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("userId", clubMember.getUid());
            jsonObject.put("memberId", clubMember.getId());
            jsonObject.put("photo", WebUtils.face(clubMember.getUid(), PORTRAIT_WIDTH));
            jsonObject.put("name", EncodeUtils.encodeForHTML(clubMember.getUser().getUsername(), sourceAgent));
            jsonObject.put("nickname", EncodeUtils.encodeForHTML(clubMember.getUser().getNickname(), sourceAgent));
            jsonObject.put("truename", EncodeUtils.encodeForHTML(clubMember.getUser().getTruename(), sourceAgent));
            String info;
            if (clubMember.getUser().getVip() == 0) {
                info = WebUtils.car(clubMember.getUser().getCarInfo());
            } else {
                info = WebUtils.car(clubMember.getUser().getVipInfo());
            }
            jsonObject.put("petrol", clubMember.getPetrol());
            jsonObject.put("vipInfo", info);
            jsonObject.put("province", EncodeUtils.encodeForHTML(clubMember.getUser().getProvince(), sourceAgent));
            jsonObject.put("city", EncodeUtils.encodeForHTML(clubMember.getUser().getCity(), sourceAgent));
            jsonObject.put("type", clubMember.getAdminType());
            jsonObject.put("phone", EncodeUtils.encodeForHTML(clubMember.getUser().getPhone(), sourceAgent));
            jsonArray.add(jsonObject);
        }
        return jsonArray;
    }

    /**
     * 取消申请
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/member/cancelApply.do", method = RequestMethod.POST, produces = {"text/html;charset=UTF-8"})
    @ResponseBody
    public String cancelApply(HttpServletRequest request, HttpServletResponse response) {
        String originHeader = request.getHeader("Origin");
        if (originHeader != null) {
            response.setHeader("Access-Control-Allow-Credentials", "true");
            response.setHeader("Access-Control-Allow-Origin", originHeader);
        }
        response.setCharacterEncoding("UTF-8");
        long memberId = WebUtils.paramLong(request, "memberId", 0);
        int windowName = WebUtils.paramInt(request, "windowname", 0);
        User user = userAuth.getUser(request, response);
        MemberApplication memberApplication = memberService.findMemberApplication(memberId);
        if (memberApplication == null) {
            return parseWindowNameString(new JsonResult(JsonResult.STATUS_AUTH_FAILED, "not found memberId").toString(), windowName);
        }
        if (clubService.getValidClub(memberApplication.getClubId()) == null) {
            return parseWindowNameString(new JsonResult(JsonResult.STATUS_AUTH_FAILED, "车友会不存在").toString(), windowName);
        }
        if (user != null && user.getUid() > 0) {
            if (memberApplication.getUid() == user.getUid()) {
                if (memberApplication.getStatus() == 0) {
                    memberService.deleteMemberApplication(memberApplication);
                } else if (memberApplication.getStatus() == MemberApplication.STATUS_PASS) {
                    return parseWindowNameString(new JsonResult(JsonResult.STATUS_AUTH_FAILED, "您已是该车友会成员").toString(), windowName);
                } else if (memberApplication.getStatus() == MemberApplication.STATUS_REJECT) {
                    return parseWindowNameString(new JsonResult(JsonResult.STATUS_AUTH_FAILED, "您加入的车友会申请已被拒绝，请尝试加入其他车友会!").toString(), windowName);
                }
                //发送消息给管理员
                Club club = clubService.getClub(memberApplication.getClubId());
                List<ClubMember> admins = memberService.listAdmins(club.getClubId());
                String clubIndexUrl = messageService.assembleClubUrl(club.getClubUrl(), club.getName());
                User ops = userService.findUser(memberApplication.getUid());
                for (ClubMember member : admins) {
                    User u = userService.findUser(member.getUid());
                    if (u != null) {
                        messageService.send(u, MessageService.CANEL_APPLY, clubIndexUrl, ops.getNickname());
                    }
                }
                return parseWindowNameString(new JsonResult(JsonResult.STATUS_SUCCESS, "OK").toString(), windowName);
            } else {
                return parseWindowNameString(new JsonResult(JsonResult.STATUS_AUTH_FAILED, "Must for operation").toString(), windowName);
            }
        } else {
            return parseWindowNameString(new JsonResult(JsonResult.STATUS_AUTH_FAILED, "User is not login").toString(), windowName);
        }
    }

    /**
     * 车友会成员管理接口
     *
     * @throws UnsupportedEncodingException
     */
    @ResponseBody
    @RequestMapping(value = "/member/operation.do", method = RequestMethod.POST)
    public JSONObject operation(HttpServletRequest req, HttpServletResponse resp) {
        WebUtils.setEncoding(req, resp);
        long clubId = WebUtils.paramLong(req, "clubId", 0);
        User user = userAuth.getUser(req, resp);
        long targetId = WebUtils.paramLong(req, "targetId", 0);
        int type = WebUtils.paramInt(req, "type", 0);
        JSONObject json = new JSONObject();
        int code = -1;
        String message = "";
        int isSendAdmin = -1;  //  -1 默认不发消息   1》给管理员发消息    2》给操作对象发消息
        long deleMemberId = 0;
        String sendMsg = "";
        Club club = clubService.getValidClub(clubId);
        if (user != null && user.getUid() > 0) {
            if (club != null) {
                String clubIndexUrl = messageService.assembleClubUrl(club.getClubUrl(), club.getName());
                if (type > 0) {
                    long resultCode = 0;
                    if (type == AppUtils.ACTION_TYPE_CANCELAPPLY) {
                        //取消申请加入
                        MemberApplication memberApplication = memberService.getMemberApplication(clubId, targetId, 99);
                        resultCode = -10;
                        if (memberApplication != null) {
                            if (memberApplication.getUid() == user.getUid()) {
                                if (memberApplication.getStatus() == MemberApplication.STATUS_PASS) {
                                    code = AppUtils.STATUS_PERMISSIONS_ERROR;
                                    message = "您已是该车友会成员";
                                } else if (memberApplication.getStatus() == MemberApplication.STATUS_REJECT) {
                                    code = AppUtils.STATUS_PERMISSIONS_ERROR;
                                    message = "您加入车友会的申请已被拒绝，请尝试加入其他车友会";
                                } else if (memberApplication.getStatus() == MemberApplication.STATUS_UNAUDITED) {
                                    //取消申请
                                    memberService.deleteMemberApplication(memberApplication);
                                    resultCode = 1;
                                    //发送消息给管理员
                                    User targetUser = userService.findUser(memberApplication.getUid());
                                    isSendAdmin = 1;
                                    sendMsg = String.format(MessageService.CANEL_APPLY, clubIndexUrl, targetUser.getNickname());
                                }
                            } else {
                                code = AppUtils.STATUS_PERMISSIONS_ERROR;
                                message = "请本人操作";
                            }

                        } else {
                            code = AppUtils.STATUS_DATA_ERROR;
                            message = "找不到该申请记录";
                        }
                    } else {
                        ClubMember operator = memberService.findMember(user.getUid(), clubId);
                        ClubMember targetMember = memberService.find(targetId);
                        if (operator == null) {
                            resultCode = -10;
                            code = AppUtils.STATUS_PERMISSIONS_ERROR;
                            message = "非车友会成员不允许操作！";
                        } else if (targetMember == null) {
                            resultCode = -10;
                            code = AppUtils.STATUS_DATA_ERROR;
                            message = "用户对象不存在";
                        } else {
                            User targetUser = userService.findUser(targetMember.getUid());
                            if (user.getUid() == targetMember.getUid() && type == AppUtils.ACTION_TYPE_REMOVECLUB) {
                                //退出车友会
                                if (!memberService.isClubMember(user.getUid(), clubId)) {
                                    resultCode = -10;
                                    code = AppUtils.STATUS_FAIL;
                                    message = "操作失败，您已被管理员移出车友会！";
                                } else if (targetMember.getAdminType() == ClubMember.ADMIN) {
                                    resultCode = -9;
                                } else {
                                    resultCode = memberService.expelMember(operator, targetMember);
                                    //发送消息给管理员
                                    isSendAdmin = 1;
                                    sendMsg = String.format(MessageService.EXIT_CLUB, clubIndexUrl, targetUser.getNickname());
                                }
                            } else if (memberService.isClubOwner(user.getUid(), clubId)) {
                                //会长
                                if (type == AppUtils.ACTION_TYPE_ASSIGNMENT) {
                                    //转让会长 
                                    resultCode = memberService.adminAssignment(operator, targetMember, 2);
                                } else if (type == AppUtils.ACTION_TYPE_SETVICE) {
                                    //设置副会长
                                    resultCode = memberService.adminAssignment(operator, targetMember, 1);
                                } else if (type == AppUtils.ACTION_TYPE_REMOVEJOB) {
                                    //移除职务 
                                    resultCode = memberService.adminAssignment(operator, targetMember, 0);
                                } else if (type == AppUtils.ACTION_TYPE_REMOVECLUB) {
                                    deleMemberId = targetMember.getUid();
                                    //移除车友会  
                                    resultCode = memberService.expelMember(operator, targetMember);
                                    isSendAdmin = 2;
                                    sendMsg = String.format(MessageService.FIRED_CLUB, clubIndexUrl);
                                }
                            } else {
                                resultCode = -10;
                                code = AppUtils.STATUS_PERMISSIONS_ERROR;
                                message = "您不是该车友会会长，只有会长才能进行该操作哦！";
                            }
                        }
                    }
                    //结果处理
                    if (resultCode > 0) {
                        code = AppUtils.STATUS_OK;
                        message = "操作成功";
                        //发消息
                        if (isSendAdmin > 0) {
                            if (isSendAdmin == 1) {
                                //发给管理员
                                List<ClubMember> listAdmin = memberService.listAdmins(clubId);
                                if (listAdmin != null && !listAdmin.isEmpty() && StringUtils.isNotBlank(sendMsg)) {
                                    List<User> users = memberService.getUserByMember(listAdmin);
                                    messageService.sendMsg(users, sendMsg);
                                }
                            } else if (isSendAdmin == 2) {
                                //发给操作用户
                                if (StringUtils.isNotBlank(sendMsg) && deleMemberId > 0) {
                                    User targetUser = userService.findUser(deleMemberId);
                                    if (targetUser != null) {
                                        messageService.send(targetUser, sendMsg);
                                    }
                                }
                                //调用融云退出群API
                                String userId_s = "";
                                String clubId_s = "";
                                try {
                                    userId_s = String.valueOf(deleMemberId);
                                    clubId_s = String.valueOf(clubId);
                                    boolean quitFlag = tokenController.QuitClub(userId_s, clubId_s);
                                    if (!quitFlag) {
                                    	//插入失败日志
                                    	cloudLogService.create(club.getClubId(),club.getName(),user.getUid(),CloudLog.QUIT_CLOUD);
                                        log.error("调用融云退出群API失败!userId=" + userId_s + ",clubId=" + clubId_s);
                                    }
                                } catch (ApiException exception) {
                                	//插入失败日志
                                	cloudLogService.create(club.getClubId(),club.getName(),user.getUid(),CloudLog.QUIT_CLOUD);
                                    log.error("调用融云退出群API异常！userId=" + userId_s + ",clubId=" + clubId_s);
                                }
                            }
                        }


                    } else if (resultCode == -9) {
                        code = AppUtils.STATUS_PERMISSIONS_ERROR;
                        message = "请转让会长后再退出车友会";
                    } else if (resultCode == -10) {
                        //跳过这层不设置code message 交由上面步骤处理
                    } else {
                        code = AppUtils.STATUS_FAIL;
                        message = "操作失败";
                    }
                } else {
                    code = AppUtils.STATUS_FAIL;
                    message = "操作类型不合法";
                }
            } else {
                code = AppUtils.STATUS_DATA_ERROR;
                message = "该车友会ID不存在";
            }
        } else {
            code = AppUtils.STATUS_NOLOGIN_ERROR;
            message = "用户未登录，请先登录";
        }
        json.put("code", code);
        json.put("message", message);
        return json;
    }

    /**
     * 展示管理员、会员列表(wap)
     *
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    @RequestMapping(value = "/wap/member/manage", method = RequestMethod.GET)
    public String toMemberList(HttpServletRequest request, HttpServletResponse response) throws IOException {
        long clubId = WebUtils.paramLong(request, "clubId", 0);
        Club club = clubService.getValidClub(clubId);
        if (club == null) {
            return "redirect:http://m.pcauto.com.cn/x/404/";
        }

        List<ClubMember> admins = memberService.listAdmins(clubId);
        request.setAttribute("club", club);
        request.setAttribute("admins", admins);//获取管理员列表        
        request.setAttribute("countMember", memberService.countMember(clubId));//普通会员数

        return "/template/wap/member/member_list";
    }

    /**
     * @throws IOException 会员列表接口(wap)
     *
     * @throws
     */
    @ResponseBody
    @RequestMapping(value = "/wap/getMemberByClubId.do", method = RequestMethod.GET)
    public void listtMemberByClubId(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        WebUtils.setEncoding(req, resp);
        String callback = WebUtils.param(req, "callback", "");
        long clubId = WebUtils.paramLong(req, "clubId", 0);
        int pageNo = WebUtils.paramInt(req, "pageNo", 1);
        int pageSize = WebUtils.paramInt(req, "pageSize", 4, MIN_PAGESIZE, MAX_PAGESIZE);
        int sourceAgent = WebUtils.paramInt(req, "source_agent", 2);
        JSONObject json = new JSONObject();
        json.put("clubId", clubId);
        if (clubService.getValidClub(clubId) != null) {
            Pager<ClubMember> pager = memberService.pagerMemberByType(clubId, 0, pageNo, pageSize);
            if (pager != null) {
                JSONArray jsonArray = new JSONArray();
                if (pager.getResultList() != null && !pager.getResultList().isEmpty()) {
                    for (ClubMember cm : pager.getResultList()) {
                        JSONObject jsonObject = new JSONObject();
                        jsonObject.put("uid", cm.getUid());
                        jsonObject.put("photo", WebUtils.face(cm.getUid(), PORTRAIT_WIDTH));
                        jsonObject.put("nickname", (EncodeUtils.encodeForHTML(cm.getUser().getNickname(), sourceAgent)));
                        jsonArray.add(jsonObject);
                    }
                    json.put("result", jsonArray);
                    json.put("total", pager.getTotal());
                    json.put("pageNo", pager.getPageNo());
                    json.put("pageSize", pager.getPageSize());
                }
            }
        } else {
            json.put("message", "车友会不存在");
        }
        printWriter(resp, json.toJSONString(), callback);
    }

    /**
     * 根据用户ID和车友会ID批量获取会员列表
     *
     * @param req
     * @param resp
     */
    @RequestMapping(value = "/member/listMemberByIds", method = RequestMethod.GET)
    public void listMemberByIds(HttpServletRequest req, HttpServletResponse resp) {
        WebUtils.setCacheHeader(resp, 3600); //缓存1h
        WebUtils.setEncoding(req, resp);
        long clubId = WebUtils.paramLong(req, "clubId", 0);
        String memberIds = WebUtils.paramTrim(req, "ids", "");
        String callback = WebUtils.param(req, "callback", "");
        callback = EncodeUtils.encodeForHTMLFilterNull(callback);
        int source_agent = WebUtils.paramInt(req, "source_agent", 2);
        int isSort = WebUtils.paramInt(req, "isSort", 0); //是否需要根据所传ID排序 默认0不排,1排
        JsonResult jsonResult = new JsonResult();
        jsonResult.setCallback(callback);
        if (StringUtils.isBlank(memberIds)) {
            jsonResult.setDesc("请输入用户ID");
            jsonResult.setStatus(JsonResult.STATUS_ILLEGAL_ARGUMENT);
            printWriter(resp, jsonResult.toString());
            return;
        }
        String[] ids = memberIds.split(",");
        Long[] memberList = new Long[ids.length];
        for (int i = 0; i < ids.length; i++) {
            try {
                memberList[i] = Long.parseLong(ids[i]);
            } catch (NumberFormatException ex) {
                log.error("根据用户ID和车友会ID批量获取会员列表方法异常!", ex);
                jsonResult.setDesc("用户ID有误");
                jsonResult.setStatus(JsonResult.STATUS_ILLEGAL_ARGUMENT);
                printWriter(resp, jsonResult.toString());
                return;
            }
        }
        JSONObject object = new JSONObject();
        JSONArray jsonArray;
        List<ClubMember> members = memberService.getClubMemberByIdList(clubId, memberList);
        if (isSort == 1) {
            List<ClubMember> sortMembers = new ArrayList<ClubMember>(members.size());
            for (long id : memberList) {
                for (ClubMember c : members) {
                    if (c.getUid() == id) {
                        sortMembers.add(c);
                    }
                }
            }
            jsonArray = member2Json(sortMembers, source_agent);
        } else {
            jsonArray = member2Json(members, source_agent);
        }
        object.put("members", jsonArray);
        object.put("clubId", clubId);
        object.put("code", AppUtils.STATUS_OK);
        jsonResult.setResult(object.toJSONString());
        printWriter(resp, jsonResult.toString());
    }

    /**
     * 返回信息方法
     *
     * @param resp
     * @param json
     */
    private void printWriter(HttpServletResponse resp, String json) {
        printWriter(resp, json, "");
    }

    /**
     * 返回信息方法
     *
     * @param resp
     * @param json
     */
    private void printWriter(HttpServletResponse resp, String json, String callback) {
        callback = EncodeUtils.encodeForHTMLFilterNull(callback);
        try {
            PrintWriter out = resp.getWriter();
            if (StringUtils.isBlank(callback)) {
                out.println(json);
            } else {
                out.println(callback + "(" + json + ")");
            }
            out.flush();
            out.close();
        } catch (IOException ex) {
            log.error("返回信息方法异常！", ex);
        }
    }

    /**
     * 更新用户经纬度
     *
     * @param req
     * @param resp
     */
    @RequestMapping(value = "/user/updateUserPosition", method = RequestMethod.POST)
    public void updateUserPosition(HttpServletRequest req, HttpServletResponse resp) {
        WebUtils.setEncoding(req, resp);
        double lon = WebUtils.paramDouble(req, "longitude", 0);//经度
        double lat = WebUtils.paramDouble(req, "latitude", 0);//纬度
        JSONObject obj = new JSONObject();
        if (lon == 0 || lat == 0) {
            obj.put("code", AppUtils.STATUS_DATA_ERROR);
            obj.put("message", "用户经纬度不能为空");
            printWriter(resp, obj.toJSONString());
            return;
        }
        //只支持国内的,经度（73--135）纬度（3--53）
        if (lon > 135 || lon < 73) {
            obj.put("code", AppUtils.STATUS_DATA_ERROR);
            obj.put("message", "用户经度范围（73-135)");
            printWriter(resp, obj.toJSONString());
            return;
        }
        if (lat > 53 || lat < 3) {
            obj.put("code", AppUtils.STATUS_DATA_ERROR);
            obj.put("message", "用户纬度范围（3-53)");
            printWriter(resp, obj.toJSONString());
            return;
        }

        User user = userAuth.getUser(req, resp);
        if (user == null) {
            obj.put("code", AppUtils.STATUS_NOLOGIN_ERROR);
            obj.put("message", "未登录");
            printWriter(resp, obj.toJSONString());
            return;
        }
        user.setLongitdue(lon);
        user.setLatitude(lat);
        int count = userService.updateUser(user);
        if (count > 0) {
            obj.put("code", AppUtils.STATUS_OK);
            obj.put("message", "更新成功");
        } else {
            obj.put("code", AppUtils.STATUS_FAIL);
            obj.put("message", "更新失败");
        }
        printWriter(resp, obj.toJSONString());
    }

    /**
     * 根据经纬度查询附近用户
     *
     * @param req
     * @param resp
     */
    @RequestMapping(value = "/user/listUserByPosition.do", method = RequestMethod.GET)
    public void listUserByPosition(HttpServletRequest req, HttpServletResponse resp) {
        //TODO性能优化： 崇锜 陈 1 week, 2 days ago (五月 4, 2015, 11:05 a.m.)查了一下，geohash这个算法可以参考一下，把坐标换算成一个数值来做数据库索引，这样查的时候就快多了
        WebUtils.setEncoding(req, resp);
        String lon = WebUtils.param(req, "longitude", "");//经度
        String lat = WebUtils.param(req, "latitude", "");//纬度
        long userId = WebUtils.paramLong(req, "userId", 0L);
        int pageNo = WebUtils.paramInt(req, "pageNo", 1);
        int pageSize = WebUtils.paramInt(req, "pageSize", 20, 0, 100);
        int source_agent = WebUtils.paramInt(req, "source_agent", 2);
        String callback = WebUtils.param(req, "callback", "");
        JSONObject obj = new JSONObject();
        if (StringUtils.isBlank(lon) || StringUtils.isBlank(lat)) {
            obj.put("code", AppUtils.STATUS_DATA_ERROR);
            obj.put("message", "查询经纬度不能为空");
            printWriter(resp, obj.toJSONString(), callback);
            return;
        }

        try {
            double longitude = Double.parseDouble(lon);
            double latitude = Double.parseDouble(lat);

            //只支持国内的,经度（73--135）纬度（3--53）
            if (longitude > 135 || longitude < 73) {
                obj.put("code", AppUtils.STATUS_DATA_ERROR);
                obj.put("message", "用户经度范围（73-135)");
                printWriter(resp, obj.toJSONString());
                return;
            }
            if (latitude > 53 || latitude < 3) {
                obj.put("code", AppUtils.STATUS_DATA_ERROR);
                obj.put("message", "用户纬度范围（3-53)");
                printWriter(resp, obj.toJSONString());
                return;
            }

            JSONArray array = new JSONArray();
            //查找所有附近的人，经纬度相关0.2度（约22公里半径）
            List<User> users = userService.findUserByPositionList(longitude, latitude, LAT_LNG_SIZE, userId);
            //对附近的人进行排序，近距离由近到远
            List<User> updateUsers = sortUserByDistance(users, longitude, latitude);
            //保存某一页的用户列表
            List<User> returnUsers = new ArrayList<User>();
            List<Long> ids = new ArrayList<Long>();
            List<Double> distances = new ArrayList<Double>();
            int beginUser = (pageNo - 1) * pageSize;
            int endUser = pageSize * pageNo < users.size() ? pageSize * pageNo : users.size();
            for (int i = beginUser; i < endUser; i++) {
                User u = updateUsers.get(i);
                returnUsers.add(u);
                ids.add(u.getUid());
                distances.add(u.getDistance());
            }
            returnUsers = geliDao.list(User.class, ids.toArray());
            for (int i = 0; i < returnUsers.size(); i++) {
                returnUsers.get(i).setDistance(distances.get(i));
            }
            //把所有的附近的人组装到Pager，可提供分页加载功能
            Pager<User> pager = new Pager<User>();
            pager.setPageNo(pageNo);
            pager.setPageSize(pageSize);
            pager.setTotal(users.size());
            pager.setResultList(returnUsers);
            if (users.isEmpty() || pageNo > pager.getPageCount() || (pageNo - 1) * pageSize < 0) {
                pager = null;
            }
            //组装需要返回的接口内容
            if (pager != null) {
                array = userToJson(pager.getResultList(), source_agent);
                obj.put("pageNo", pager.getPageNo());
                obj.put("total", pager.getTotal());
                obj.put("pageSize", pager.getPageSize());
                obj.put("pageCount", pager.getPageCount());
            }
            obj.put("data", array);
            obj.put("code", AppUtils.STATUS_OK);
            printWriter(resp, obj.toJSONString(), callback);
        } catch (NumberFormatException ex) {
            obj.put("code", AppUtils.STATUS_DATA_ERROR);
            obj.put("message", "经纬度有误");
            printWriter(resp, EncodeUtils.encodeForHTML(obj.toJSONString(), source_agent), callback);
        }
    }

    /**
     * 获取附近的人的距离，并按距离由近到远进行排序
     *
     * @param users需要进行排序的用户列表
     * @param longitude经度
     * @param latitude纬度
     * @return
     */
    public List<User> sortUserByDistance(List<User> users, double longitude, double latitude) {
        List<User> updateUsers = new ArrayList<User>(users.size());
        //获取附近人的距离
        for (User user : users) {
            double distance = getDistance(latitude, longitude, user.getLatitude(), user.getLongitdue());
            user.setDistance(distance);
            updateUsers.add(user);
        }
        //内部类用于对距离进行排序
        class UserComparator implements Comparator<User> {

            @Override
            public int compare(User user1, User user2) {
                double distance1 = user1.getDistance();
                double distance2 = user2.getDistance();

                if (distance1 > distance2) {
                    return 1;
                } else {
                    return -1;
                }
            }
        }
        //比较距离得到排序后的用户列表
        UserComparator userComparator = new UserComparator();
        Collections.sort(updateUsers, userComparator);
        return updateUsers;
    }

    @RequestMapping(value = "/user/isClubAdmin", method = RequestMethod.GET)
    public void isClubAdmin(HttpServletRequest req, HttpServletResponse resp) {
        WebUtils.setEncoding(req, resp);
        int source_agent = WebUtils.paramInt(req, "source_agent", 1);
        String callback = WebUtils.param(req, "callback", "");

        User user = userAuth.getUser(req, resp);

        JSONObject obj = new JSONObject();
        if (user.getUid() == User.ANONYMOUS.getUid()) {
            obj.put("code", -1);
            obj.put("message", "用户未登录");
        } else {
            ClubMember clubMember = memberService.findClubMemberByUserId(user.getUid());
            if (clubMember != null) {
                int adminType = clubMember.getAdminType();
                if (adminType == ClubMember.ADMIN) {
                    obj.put("code", 0);
                    obj.put("message", "用户会长");
                } else if (adminType == ClubMember.VICE_ADMIN) {
                    obj.put("code", 0);
                    obj.put("message", "用户副会长");
                } else {
                    obj.put("code", -2);
                    obj.put("message", "用户非会长/副会长");
                }
            } else {
                obj.put("code", -3);
                obj.put("message", "用户未加入车友会");
            }
        }
        printWriter(resp, EncodeUtils.encodeForHTML(obj.toJSONString(), source_agent), callback);
    }

    /**
     * 组装附近的人接口的返回内容
     *
     * @param user
     * @param source_agent
     * @return
     */
    private JSONArray userToJson(List<User> user, int source_agent) {
        if (user == null) {
            return null;
        }
        JSONArray array = new JSONArray();
        for (User u : user) {
            JSONObject obj = new JSONObject();
            obj.put("userId", u.getUid());
            obj.put("sex", u.getGender() == 0 ? "男" : "女");
            obj.put("userImg", WebUtils.face(u.getUid(), PORTRAIT_WIDTH, AUTHORPHOTO_URL_I6));
            obj.put("nickName", EncodeUtils.encodeForHTML(u.getNickname(), source_agent));
            obj.put("vip", u.getVip());
            //截取认证车系名字（brandId;brandName;seriesId,seriesName）
            String serialName = u.getVipInfo();
            if (StringUtils.isBlank(serialName)) {
                obj.put("serialName", "");
            } else {
                int beginIndex = serialName.lastIndexOf(";");
                obj.put("serialName", serialName.substring(beginIndex + 1));
            }
            double distance = u.getDistance();

            //如果小于1公里，返回以米为单位
            //如果不小于1公里，返回心公里为单位（如果是整公里，不带小数点）
            String distanceStr;
            if (distance >= 1) {
                DecimalFormat df = new DecimalFormat("0.0");
                distanceStr = df.format(distance);
                if (distanceStr.split("\\.")[1].equals("0")) {
                    distanceStr = distanceStr.split("\\.")[0];
                }
                distanceStr += "km";
            } else {
                DecimalFormat df = new DecimalFormat("0");
                distanceStr = df.format(distance * 1000) + "m";
            }
            obj.put("longitude", u.getLongitdue());
            obj.put("latitude", u.getLatitude());
            obj.put("distance", distanceStr);
            array.add(obj);
        }
        return array;
    }

    private double Rad(double d) {
        return d * Math.PI / 180.0;
    }

    /**
     * 查询两个经纬度之间的距离
     *
     * @param lat1
     * @param lng1
     * @param lat2
     * @param lng2
     * @return
     */
    public double getDistance(double lat1, double lng1, double lat2, double lng2) {
        double EARTH_RADIUS = 6378.137;//地球半径
        double radLat1 = Rad(lat1);
        double radLat2 = Rad(lat2);
        double a = radLat1 - radLat2;
        double b = Rad(lng1) - Rad(lng2);
        double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2)
                + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
        s = s * EARTH_RADIUS;
        return s;
    }

    private Pager<ClubMember> searchMember(long clubId, String keyword, int pageNo, int pageSize) {
        Pager<ClubMember> members;
        if (StringUtils.isNumeric(keyword)) {//关键字是否是纯数字,纯数字只匹配昵称,不匹配车系
            members = memberService.searchMember(clubId, keyword, pageNo, pageSize, false);
        } else {
            members = memberService.searchMember(clubId, keyword, pageNo, pageSize, true);
        }
        return members;
    }

    private Pager<ClubMember> getAllMember(long clubId, int type, int pageNo, int pageSize) {
        Pager<ClubMember> members = null;
        if (type == TYPE_ALL) {
            members = memberService.getClubMemberPage(clubId, 0l, pageNo, pageSize);
        } else if (type == TYPE_CERTIFIED) {
            members = memberService.listVipMember(clubId, ClubMember.IS_VIP, pageNo, pageSize);
        } else if (type == TYPE_ORDINARY) {
            members = memberService.listVipMember(clubId, ClubMember.NOT_VIP, pageNo, pageSize);
        }
        return members;
    }

    /**
     * 会员列表(List)
     *
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    @RequestMapping(value = "/member/manageList", method = RequestMethod.GET)
    public String toMemberManagementForList(HttpServletRequest request, HttpServletResponse response) {
        long clubId = WebUtils.paramLong(request, "clubId", 0);
        Club club = clubService.getValidClub(clubId);
        int type = WebUtils.paramInt(request, "type", TYPE_ALL);
        String keyword = WebUtils.param(request, "keyword", "");
        int pageNo = WebUtils.paramInt(request, "pageNo", 1);
        int pageSize = WebUtils.paramInt(request, "pageSize", 15, MIN_PAGESIZE, MAX_PAGESIZE);
        if (club == null || pageNo < 1) {
            try {
                response.sendError(404);
            } catch (Exception e) {
                log.error("toMemberManagement response.sendError(404) 失败", e);
            }
            return "/template/common/notFoundPage";
        }
        request.setAttribute("club", club);
        User loginUser = userAuth.getUser(request, response);
        if (!memberService.isClubNormalAdmin(loginUser.getUid(), clubId)) {
            try {
                response.sendError(403);
            } catch (IOException ex) {
                log.error("访问会员详细列表无权限跳转错误:" + ex);
            }
            return "/template/common/notAuthPage";
        }
        List<MemberApplication> applications = memberService.listMemberApplications4Audit(clubId);
        request.setAttribute("applications", applications);

        // Pager<ClubMember> members = getAllMember(clubId, type, pageNo, pageSize);
        Pager<ClubMember> members = null;
        if ("".equals(keyword)) {
            members = getAllMember(clubId, type, pageNo, pageSize);
        } else {//如果keyword不为空，则为快速查询
            members = searchMember(clubId, keyword, pageNo, pageSize);
        }

        WebUtils.checkPageMaxNo(response, pageNo, members.getPageCount());
        request.setAttribute("members", members);
        if (loginUser.getUid() != 0L) {
            request.setAttribute("user", loginUser);
            ClubMember clubMember = memberService.findMember(loginUser.getUid(), clubId);
            request.setAttribute("loginClubMember", clubMember);
        }
        request.setAttribute("type", type);
        request.setAttribute("totalCount", club.getMemberNum());
        request.setAttribute("keyword", keyword);
        ClubController.setClubStyle(request, clubId);
        return "template/member/memberList";
    }

    /**
     * 会员方格列表
     *
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    @RequestMapping(value = "/member/memberGridList")
    public String toMemberGridList(HttpServletRequest request, HttpServletResponse response) throws IOException {
        WebUtils.setEncoding(request, response);
        long clubId = WebUtils.paramLong(request, "clubId", 0);
        Club club = clubService.getValidClub(clubId);
        int pageNo = WebUtils.paramInt(request, "pageNo", 1);
        int type = WebUtils.paramInt(request, "type", TYPE_ALL);
        String keyword = WebUtils.param(request, "keyword", "");
        int pageSize = WebUtils.paramInt(request, "pageSize", 30, MIN_PAGESIZE, MAX_PAGESIZE);
        if (club == null || pageNo < 1) {
            try {
                response.sendError(404);
            } catch (Exception e) {
                log.error("toMemberManagement response.sendError(404) 失败", e);
            }
            return "/template/common/notFoundPage";
        }
        request.setAttribute("club", club);
        request.setAttribute("clubId", clubId);
        request.setAttribute("type", type);
        //申请加入该车友会用户
        List<MemberApplication> applications = memberService.listMemberApplications4Audit(clubId);
        request.setAttribute("applications", applications);
        Pager<ClubMember> members;
        if ("".equals(keyword)) {
            members = getAllMember(clubId, type, pageNo, pageSize);
        } else {//如果keyword不为空，则为快速查询
            members = searchMember(clubId, keyword, pageNo, pageSize);
        }
        WebUtils.checkPageMaxNo(response, pageNo, members.getPageCount());
        request.setAttribute("members", members);
        User loginUser = userAuth.getUser(request, response);
        if (loginUser.getUid() != 0L) {
            request.setAttribute("user", loginUser);
            ClubMember clubMember = memberService.findMember(loginUser.getUid(), clubId);
            request.setAttribute("loginClubMember", clubMember);
        }
        request.setAttribute("keyword", keyword);
        ClubController.setClubStyle(request, club.getClubId());
        return "template/member/memberGridList";
    }

    /**
     * 修改备注名称
     *
     * @param req
     * @param resp
     */
    @RequestMapping(value = "/member/editRemarkName", method = RequestMethod.POST)
    public void editRemarkName(HttpServletRequest req, HttpServletResponse resp) {
        WebUtils.setEncoding(req, resp);
        long memberId = WebUtils.paramInt(req, "memberId", 0);
        long clubId = WebUtils.paramLong(req, "clubId", 0);
        String name = WebUtils.param(req, "name", "");
        User user = userAuth.getUser(req, resp);
        if (name.length() > 20) {//如果输入的备注名大于20位就截取前20位字符做为备注名保存
            name = name.substring(0, 20);
        }
        if (user == null || user.getUid() == 0) {
            printWriter(resp, "{\"code\":-1,\"message\":\"请先登录\"}");
            return;
        }
        boolean isAdmin = memberService.isClubNormalAdmin(user.getUid(), clubId);
        if (!isAdmin) {
            printWriter(resp, "{\"code\":-1,\"message\":\"只有会长或副会长才能操作\"}");
            return;
        }
        ClubMember clubMember = memberService.find(memberId);
        if (clubMember == null) {
            printWriter(resp, "{\"code\":-1,\"message\":\"会员ID有误\"}");
            return;
        }
        if (clubMember.getClubId() != clubId) {
            printWriter(resp, "{\"code\":-1,\"message\":\"参数有误\"}");
            return;
        }
        clubMember.setRemarkName(name);
        int count = memberService.updateClubMember(clubMember);
        if (count > 0) {
            printWriter(resp, "{\"code\":0,\"message\":\"修改成功\"}");
        } else {
            printWriter(resp, "{\"code\":-1,\"message\":\"修改失败\"}");
        }
    }

    /**
     * 修改备注名称页面跳转
     *
     * @param req
     * @param resp
     * @return
     */
    @RequestMapping(value = "/member/goToEditRemarkName", method = RequestMethod.GET)
    public String goToEditRemarkName(HttpServletRequest req, HttpServletResponse resp) {
        long memberId = WebUtils.paramLong(req, "memberId", 0);
        long clubId = WebUtils.paramLong(req, "clubId", 0);
        User user = userAuth.getUser(req, resp);
        if (user == null || user.getUid() == 0) {
            req.setAttribute("message", "请先登录");
            return "template/common/promptPage";
        }
        boolean isAdmin = memberService.isClubNormalAdmin(user.getUid(), clubId);
        if (!isAdmin) {
            req.setAttribute("message", "只有会长或副会长才能修改备注");
            return "template/common/promptPage";
        }
        ClubMember clubMember = memberService.find(memberId);
        if (clubMember == null) {
            req.setAttribute("message", "memberId有误");
            return "template/common/promptPage";
        }
        if (clubMember.getClubId() != clubId) {
            req.setAttribute("message", "参数有误");
            return "";
        }
        req.setAttribute("memberId", memberId);
        req.setAttribute("clubMember", clubMember);
        req.setAttribute("clubId", clubId);
        return "template/member/edit";
    }

    /**
     * 周排行榜
     *
     * @param:
     * @param request
     * @param:
     * @param response
     * @return: String
     */
    @RequestMapping(value = "/member/weekRank", method = RequestMethod.GET)
    public String weekRank(HttpServletRequest request, HttpServletResponse response) {
        long clubId = WebUtils.paramLong(request, "clubId", 0);
        Club club = clubService.getValidClub(clubId);
        int pageNo = WebUtils.paramInt(request, "pageNo", 1);
        int pageSize = WebUtils.paramInt(request, "pageSize", 20, MIN_PAGESIZE, MAX_PAGESIZE);
        if (club == null || pageNo < 1) {
            try {
                response.sendError(404);
            } catch (Exception e) {
                log.error("weekRank response.sendError(404) 失败", e);
            }
            return "/template/common/notFoundPage";
        }
        Pager<MemberWeek> pager = statService.pagerMemberWeek(clubId, pageNo, pageSize);
        WebUtils.checkPageMaxNo(response, pageNo, pager.getPageCount());//超过最大页数，404
        User user = userAuth.getUser(request, response);
        List<MemberWeek> list = pager.getResultList();
        if (list != null && list.size() > 0) {
            for (MemberWeek week : list) {
                ClubMember clubMember = memberService.findMember(week.getUserId(), clubId);
                week.setClubMember(clubMember);
            }
        }
        //申请加入该车友会用户
        List<MemberApplication> applications = memberService.listMemberApplications4Audit(clubId);
        request.setAttribute("applications", applications);
        if (user.getUid() != 0L) {
            ClubMember clubMember = memberService.findMember(user.getUid(), clubId);
            request.setAttribute("loginClubMember", clubMember);
        }
        request.setAttribute("pageNo", pageNo);
        request.setAttribute("pageSize", pageSize);
        request.setAttribute("userId", user.getUid());
        request.setAttribute("user", user);
        request.setAttribute("pager", pager);
        request.setAttribute("clubId", clubId);
        request.setAttribute("club", club);
        ClubController.setClubStyle(request, club.getClubId());
        return "template/member/week_rank";
    }

    @RequestMapping(value = "/member/allRank", method = RequestMethod.GET)
    public String allRank(HttpServletRequest request, HttpServletResponse response) {
        long clubId = WebUtils.paramLong(request, "clubId", 0);
        Club club = clubService.getValidClub(clubId);
        int pageNo = WebUtils.paramInt(request, "pageNo", 1);
        int pageSize = WebUtils.paramInt(request, "pageSize", 20, MIN_PAGESIZE, MAX_PAGESIZE);
        if (club == null || pageNo < 1) {
            try {
                response.sendError(404);
            } catch (Exception e) {
                log.error("weekRank response.sendError(404) 失败", e);
            }
            return "/template/common/notFoundPage";
        }
        Pager<MemberAll> pager = statService.pagerMemberAll(clubId, pageNo, pageSize);
        User user = userAuth.getUser(request, response);
        List<MemberAll> list = pager.getResultList();
        if (list != null && list.size() > 0) {
            for (MemberAll all : list) {
                ClubMember clubMember = memberService.findMember(all.getUserId(), clubId);
                all.setClubMember(clubMember);
            }
        }
        //申请加入该车友会用户
        List<MemberApplication> applications = memberService.listMemberApplications4Audit(clubId);
        request.setAttribute("applications", applications);
        if (user.getUid() != 0L) {
            ClubMember clubMember = memberService.findMember(user.getUid(), clubId);
            request.setAttribute("loginClubMember", clubMember);
        }

        request.setAttribute("pageNo", pageNo);
        request.setAttribute("pageSize", pageSize);
        request.setAttribute("pager", pager);
        request.setAttribute("userId", user.getUid());
        request.setAttribute("user", user);
        request.setAttribute("clubId", clubId);
        request.setAttribute("club", club);
        ClubController.setClubStyle(request, club.getClubId());
        return "template/member/all_rank";
    }

    /**
     * 快速查询：关键字为空提示页面
     *
     * @param req
     * @param resp
     * @return
     */
    @RequestMapping(value = "/member/emptyTip", method = RequestMethod.GET)
    public String emptyTip(HttpServletRequest req, HttpServletResponse resp) {
        return "template/member/emptyTip";
    }

    /**
     * 一键邀请(加入)
     *
     * @param req
     * @param resp
     */
    @RequestMapping(value = "/member/inviteJoin.do", method = RequestMethod.POST)
    public void inviteJoinClub(HttpServletRequest req, HttpServletResponse resp) {
        WebUtils.setEncoding(req, resp);
        String code = WebUtils.param(req, "code", "");
        String nickName = WebUtils.param(req, "nickName", "");
        String telePhone = WebUtils.param(req, "telePhone", "");
        int gender = WebUtils.paramInt(req, "sex", User.MALE);
        long provinceId = WebUtils.paramLong(req, "provinceId", 0);
        String provinceName = WebUtils.param(req, "provinceName", "");
        long cityId = WebUtils.paramLong(req, "cityId", 0);
        String cityName = WebUtils.param(req, "cityName", "");
        int brandId = WebUtils.paramInt(req, "brandId", 0);
        int serialId = WebUtils.paramInt(req, "serialId", 0);
        if (StringUtils.isBlank(code)) {
            printWriter(resp, new JsonResult(JsonResult.STATUS_ERROR, "参数不对").toString());
            return;
        }
        InviteJoin inviteJoin = inviteJoinService.getInviteJoinByCode(code);
        if (inviteJoin == null) {
            printWriter(resp, new JsonResult(JsonResult.STATUS_ERROR, "邀请链接已过期").toString());
            return;
        }
        Club club = clubService.getValidClub(inviteJoin.getClubId());
        if (club == null) {
            printWriter(resp, new JsonResult(JsonResult.STATUS_ERROR, "邀请链接已过期").toString());
            return;
        }
        if (StringUtils.isBlank(nickName) || !nickName.matches("([a-zA-Z0-9_]|[^\\x00-\\xff])+")) {
            JSONObject obj = new JSONObject();
            obj.put("field", "nickname");
            obj.put("message", "昵称由1-16个字符(字母、数字或下划线)或1-8个中文组成");
            printWriter(resp, new JsonResult(JsonResult.STATUS_ILLEGAL_ARGUMENT, obj.toJSONString()).toString());
            return;
        }
        if (StringUtils.isBlank(telePhone) || !telePhone.matches(Regex.cellphone.value)) {
            JSONObject obj = new JSONObject();
            obj.put("field", "telephone");
            obj.put("message", "请输入正确的手机号码");
            printWriter(resp, new JsonResult(JsonResult.STATUS_ILLEGAL_ARGUMENT, obj.toJSONString()).toString());
            return;
        }
        if (provinceId <= 0 || cityId <= 0) {
            JSONObject obj = new JSONObject();
            obj.put("field", "area");
            obj.put("message", "请选择地区");
            printWriter(resp, new JsonResult(JsonResult.STATUS_ILLEGAL_ARGUMENT, obj.toJSONString()).toString());
            return;
        }
        //验证登录
        User user = userAuth.getUser(req, resp);
        if (!isLogin(user)) {
            printWriter(resp, new JsonResult(JsonResult.STATUS_ERROR, "请先登录").toString());
            return;
        }
        if (memberService.isClubMember(user.getUid(), club.getClubId())) {
            printWriter(resp, new JsonResult(JsonResult.STATUS_ERROR, "已经加入该车友会").toString());
            return;
        }
        //验证加入车友会个数
        int count = userService.updateJoinedClubCount(user);
        if (count >= NumberUtils.toInt(systemConfig.getJoinClubLimit(), 1)) {
            printWriter(resp, new JsonResult(JsonResult.STATUS_ERROR, "已经加入其他车友会,无法再加入该车友会").toString());
            return;
        }
        if (!memberService.findMemberApplication(user.getUid(), club.getClubId(), true).isEmpty()) {
            printWriter(resp, new JsonResult(JsonResult.STATUS_ERROR, "您已经提交申请加入，请等待会长审核").toString());
            return;
        }
        if (!memberService.listClubMemberByUser(user.getUid()).isEmpty() || !clubService.findByFounder(user.getUid(), true).isEmpty()) { //已经申请加入另一个车友会 或 已创建一个车友会待审核
            printWriter(resp, new JsonResult(JsonResult.STATUS_ERROR, "您只能申请或加入一个车友会").toString());
            return;
        }
        user.setNickname(nickName);
        user.setProvinceId(provinceId);
        user.setProvince(provinceName);
        user.setCityId(cityId);
        user.setCity(cityName);
        //更新车友会用户的爱车信息
        String carInfo = getCarInfo(req);
        user.setCarInfo(carInfo);
        userService.updateUser(user);

        long id = memberService.createMemberInfo(club.getClubId(), user, ClubMember.NON_ADMIN);
        if (id > 0) {
            //加入车友会之后，初始化车友圈
            userForumService.createIfNothing(user.getUid(), cityId, provinceId, serialId);
            User inviter = userService.findUser(inviteJoin.getCreateBy());
            User admin = new User();
            ClubMember admins = memberService.findAdminByClubId(club.getClubId());
            admin.setUid(admins.getUid());//只需要会长ID
            //更新邀请链接邀请人数
            inviteJoin.setInvitedCount(inviteJoin.getInvitedCount() + 1);
            inviteJoinService.updateInviteJoinCount(inviteJoin);
            //创建邀请记录
            InviteMember inviteMember = new InviteMember();
            inviteMember.setInviteId(inviteJoin.getInviteId());
            inviteMember.setUserId(user.getUid());
            inviteMember.setJoinAt(new Date());
            inviteMemberService.createInviteMember(inviteMember);

            Cookie c = new Cookie("isFirstJoin", "true");
            c.setPath("/");
            c.setDomain(".pcauto.com.cn");
            //     c.setMaxAge(10);
            resp.addCookie(c);
            JSONObject obj = new JSONObject();
            obj.put("status", JsonResult.STATUS_SUCCESS);
            obj.put("url", club.getClubUrl());
            obj.put("desc", "加入成功");
            printWriter(resp, obj.toJSONString());

            //当没选择市传省ID,都没选择不传
            long domicileId = cityId > 0 ? cityId : provinceId > 0 ? provinceId : 0;
            //同步个人资料到个人中心
            String commonSessionId = cn.pconline.passport2.util.WebUtils.getCookie(req, systemConfig.getUserSessionName());
            intfService.updateUserCenter(commonSessionId, null, nickName, gender, telePhone, null, null, domicileId,null);
            //同步爱车信息到个人中心
            if (brandId > 0 && serialId > 0) {
                intfService.checkBrandSerial(brandId, serialId, systemConfig.getUserSessionName(),
                        WebUtils.cookie(req, systemConfig.getUserSessionName()));
            }
            //发消息给会长
            messageService.send(admin, MessageService.INVITE_JOIN_CLUB_SUCCESS_MSG,
                    user.getUid(), user.getNickname(), inviter.getUid(), inviter.getNickname(), club.getClubUrl(), club.getName());
            //给加入会员发系统消息
            String msg = String.format(MessageService.INVITE_JOIN_APPLY_SUCCESS_MSG,messageService.assembleClubUrl(club.getClubUrl(), club.getName()));
            messageService.send(user.getUid(), msg);
            //发短信通知会员
            messageService.sendSMS(telePhone, user.getUid(), MessageService.APPLY_PASS_SMS, club.getName());
            //发邮件通知会员
            if (user.getEmail() != null && user.getEmail().matches(Regex.email.value)) {
                String[] mailToAddress = {user.getEmail()};
                String subject = String.format(MessageService.APPLY_PASS_MAIL_SUBJECT, club.getName());
                VelocityContext velocityContext = new VelocityContext();
                velocityContext.put("nickName", user.getNickname());
                velocityContext.put("clubName", club.getName());
                velocityContext.put("clubUrl", club.getClubUrl());
                velocityContext.put("ucRoot", systemConfig.getUcRoot());
                velocityContext.put("userId", user.getUid());
                velocityContext.put("root", systemConfig.getRoot());
                String content = TmplUtils.render(systemConfig.getDataPath() + File.separator, "applyPassMailTempate.html", velocityContext);
                MailSenderInfo mailInfo = SimpleMailSender.getSenderInfo(systemConfig.getMailServerHost(), systemConfig.getMailServerPort(),
                        true, systemConfig.getMailPassWord(), systemConfig.getFromAddress(), mailToAddress, subject, content);
                if (SimpleMailSender.sendHtmlMail(mailInfo)) {
                    log.info("success to send mail for user[{}]", user.getUid());
                } else {
                    log.error("fail success to send mail for user[{}]", user.getUid());
                }
            }
            //通过车友会申请后，调用融云加入聊天群接口
            String userId_s = "";
            String clubId_s = "";
            String clubName = "";
            try {
                userId_s = String.valueOf(user.getUid());
                clubId_s = String.valueOf(club.getClubId());
                clubName = club.getName();

                boolean joinFlag = tokenController.joinClub(userId_s, clubId_s, clubName);
                if (!joinFlag) {
                	//插入融云失败的日志记录
                	cloudLogService.create(club.getClubId(),club.getName(),user.getUid(),CloudLog.JOIN_CLOUD);
                    log.error("调用融云加入群API失败!userId=" + userId_s + ",clubId=" + clubId_s + ",clubName=" + clubName);
                }
            } catch (ApiException exception) {
            	//插入融云失败的日志记录
            	cloudLogService.create(club.getClubId(),club.getName(),user.getUid(),CloudLog.JOIN_CLOUD);
                log.error("调用融云加入群API异常！userId=" + userId_s + ",clubId=" + clubId_s + ",clubName=" + clubName, exception);
            }
        }
    }

    private boolean isLogin(User user) {
        if (user == null || user.getUid() == 0) {
            return false;
        }
        return true;
    }

    /**
     * 获取请求中的爱车信息
     *
     * @param request
     * @return
     */
    private String getCarInfo(HttpServletRequest request) {
        String brand = WebUtils.paramTrim(request, "brandId", "");
        String serial = WebUtils.paramTrim(request, "serialId", "");
        String brandName = WebUtils.getAreaPlaceByReq(request, "brandName", "").trim();
        String serialName = WebUtils.paramTrim(request, "serialName", "");
        String carInfo = "";
        if(serial.startsWith("+")||brand.startsWith("+")){//忽略脏数据，正常不应该有这些数据
            return carInfo;
        }
        if(brandName.matches("^[A-Z] .*")){//如：A 奥迪 去掉前面的“A ”
            brandName=brandName.substring(2,brandName.length());
        }
        if (!brand.isEmpty() && !brand.equals("0") && !brandName.isEmpty()) {
            carInfo += brand + ";" + brandName + ";";
        }
        if (!serial.isEmpty() && !serial.equals("0") && !serialName.isEmpty()) {
            carInfo += serial + ";" + serialName + ";";
        }
        if (carInfo.endsWith(";")) {
            carInfo = carInfo.substring(0, carInfo.length() - 1);
        }
        if (carInfo.length() > DB_MAX_LENGTH) {
            return null;
        }
        return carInfo;
    }

    /**
     * 根据用户ID，获取用户相关信息 1. 是否为认证车主 2. 是否加入车友会 3. 车友会的相关信息（车友会名字，车友会URL） 4.
     * 车友会中的成员角色 5. 车友会中贡献的油值
     *
     * 如果不传参数userId，从登录信息中获取用户信息
     *
     * @param request
     * @param response
     */
    @RequestMapping(value = "/1.0/user/getUserCertainInfo.do", method = RequestMethod.GET)
    public void getUserCertainInfo(HttpServletRequest request, HttpServletResponse response) {
        WebUtils.setEncoding(request, response);
        long userId = WebUtils.paramLong(request, "userId", 0);
        String callback = WebUtils.param(request, "callback", "");

        JSONObject json = new JSONObject();

        User user = null;
        if (userId == 0) {//不传参，从Cookie中获取用户信息
            user = userAuth.getUser(request, response);
        } else {//使用传参查找用户信息
            user = userService.findUser(userId);
        }

        //判断用户是否合法
        if (user == null) {
            json.put("code", 1);
            json.put("message", "用户未登录或非法参数userId");
            printWriter(response, json.toJSONString(), callback);
            return;
        }

        //是否为认证车主
        long isVip = user.getVip();//0：未认证；1：已认证
        //是否加入车友会
        List<Club> joinClubs = clubService.listByUserId(user.getUid());
        int isJoinClub = 0;//0：未加入车友会；1：已加入车友会
        String clubName = "";
        String clubUrl = "";
        //用户在车友会的身份
        int adminType = 0;//0：普通会员；1：副会长；2：会长
        //贡献油值
        long petrol = 0;

        if (!joinClubs.isEmpty()) {
            isJoinClub = 1;
            Club club = joinClubs.get(0);
            if (club != null) {
                clubName = club.getName();
                clubUrl = club.getClubUrl();
                //用户在车友会的身份
                ClubMember clubMember = memberService.findMember(user.getUid(), club.getClubId());
                if (clubMember != null) {
                    adminType = clubMember.getAdminType();
                    petrol = clubMember.getPetrol();
                }
            }
        }

        JSONObject userInfo = new JSONObject();
        userInfo.put("isVip", isVip);
        userInfo.put("isJoinClub", isJoinClub);
        userInfo.put("clubName", clubName);
        userInfo.put("clubUrl", clubUrl);
        userInfo.put("adminType", adminType);
        userInfo.put("petrol", petrol);

        json.put("userInfo", userInfo);
        json.put("code", 0);
        json.put("message", "操作成功");

        printWriter(response, json.toJSONString(), callback);
    }

    @ResponseBody
    @RequestMapping(value = "/member/updateGuide.do", method = RequestMethod.POST)
    public void updateGuide(HttpServletRequest request, HttpServletResponse response) {
        WebUtils.setEncoding(request, response);
        String callback = WebUtils.param(request, "callback", "");
        String retStr = "";
        User user = userAuth.getUser(request, response);
        int adminType = -1;
        if (user != null && user.getUid() > 0) {
            ClubMember clubMember = memberService.findClubMemberByUserId(user.getUid());
            if (clubMember != null) {
                adminType = clubMember.getAdminType();
                if (adminType == ClubMember.NON_ADMIN) {
                    user.setIsLookedMemberGuide(User.LOOKED_MEMBER_GUIDE);
                    geliDao.update(user, "is_looked_member_guide");
                } else {
                    user.setIsLookedAdminGuide(User.LOOKED_ADMIN_GUIDE);
                    geliDao.update(user, "is_looked_admin_guide");
                }
                retStr = new JsonResult(JsonResult.STATUS_SUCCESS, "ok").toString();
            }
        } else {
            retStr = new JsonResult(JsonResult.STATUS_ERROR, "请登录").toString();
        }
        printWriter(response, retStr, callback);
    }
}
